package com.lark.web.controller;

import com.github.pagehelper.PageInfo;
import com.jcraft.jsch.*;
import com.lark.common.annotation.Log;
import com.lark.common.core.controller.BaseController;
import com.lark.common.core.domain.R;
import com.lark.common.core.page.PageDomain;
import com.lark.common.enums.BusinessType;
import com.lark.common.exception.CustomException;
import com.lark.common.utils.file.FileUtils;
import com.lark.common.utils.poi.ExcelUtil;
import com.lark.framework.cache.DictUtils;
import com.lark.web.domain.FileSystem;
import com.lark.web.domain.Host;
import com.lark.web.service.FileSystemService;
import com.lark.web.service.HostService;
import com.lark.web.ssh.service.SSHUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 文件中心Controller
 *
 * @author fei
 * @email zhangfei0210@163.com
 * @date 2024-09-10
 */
@RestController
@RequestMapping("/dockerinsight/fileSystem")
public class FileSystemController extends BaseController {

    @Autowired
    private FileSystemService fileSystemService;
    @Autowired
    private HostService hostService;

    /**
     * 查看文件内容
     */
    @PreAuthorize("@ss.hasPermi('dockerinsight:fileSystem:list')")
    @GetMapping("/viewFile")
    public R viewFile(@RequestParam("ip") String ip, @RequestParam("currentPath") String currentPath, @RequestParam("fileName") String fileName) {
        if (StringUtils.isBlank(currentPath)) {
            currentPath = "/";
        }
        if (!currentPath.endsWith("/")) {
            currentPath += "/";
        }
        return R.data(fileSystemService.viewFile(ip, currentPath + fileName));
    }

    /**
     * 重命名文件
     */
    @PreAuthorize("@ss.hasPermi('dockerinsight:fileSystem:edit')")
    @Log(title = "重命名文件", businessType = BusinessType.UPDATE)
    @PutMapping("renameFile")
    public R renameFile(@RequestParam("ip") String ip, @RequestParam("currentPath") String currentPath, @RequestParam("fileName") String fileName, @RequestParam("newFileName") String newFileName) {
        if (StringUtils.isBlank(currentPath)) {
            currentPath = "/";
        }
        if (!currentPath.endsWith("/")) {
            currentPath += "/";
        }
        fileSystemService.renameFile(ip,fileName,currentPath,newFileName);
        return R.success();
    }

    /**
     * 新增文件夹
     */
    @PreAuthorize("@ss.hasPermi('dockerinsight:fileSystem:add')")
    @Log(title = "新增文件夹", businessType = BusinessType.INSERT)
        @PostMapping("/createDir")
    public R createDir(@RequestBody @Validated FileSystem fileSystem) {
        String currentPath = fileSystem.getCurrentPath();
        if (StringUtils.isBlank(currentPath)) {
            currentPath = "/";
        }
        if (!currentPath.endsWith("/")) {
            currentPath += "/";
        }
        return R.data(fileSystemService.createFile(fileSystem.getIp(), "directory", fileSystem.getNewFileName(), currentPath));
    }

    /**
     * 新增普通文件
     */
    @PreAuthorize("@ss.hasPermi('dockerinsight:fileSystem:add')")
    @Log(title = "新增普通文件", businessType = BusinessType.INSERT)
    @PostMapping("createFile")
    public R createFile(@RequestBody @Validated FileSystem fileSystem) {
        String currentPath = fileSystem.getCurrentPath();
        if (StringUtils.isBlank(currentPath)) {
            currentPath = "/";
        }
        if (!currentPath.endsWith("/")) {
            currentPath += "/";
        }
        return R.data(fileSystemService.createFile(fileSystem.getIp(), "regular_file", fileSystem.getNewFileName(), currentPath));
    }

    /**
     * 删除文件或者文件夹
     */
    @PreAuthorize("@ss.hasPermi('dockerinsight:fileSystem:remove')")
    @Log(title = "删除文件或者文件夹", businessType = BusinessType.DELETE)
    @DeleteMapping("removeFile")
    public R removeFile(@RequestParam("ip") String ip, @RequestParam("currentPath") String currentPath, @RequestParam("fileName") String fileName) {
        if (StringUtils.isBlank(currentPath)) {
            currentPath = "/";
        }
        if (!currentPath.endsWith("/")) {
            currentPath += "/";
        }
        return R.data(fileSystemService.removeFile(ip, currentPath + fileName));
    }

    /**
     * 上传文件
     *
     * @param file
     * @param currentPath
     * @param ip
     * @return
     */
    @PostMapping("/upload")
    @Log(title = "上传文件", businessType = BusinessType.INSERT)
    public R handleFileUpload(@RequestParam("file") MultipartFile file, @RequestParam("currentPath") String currentPath, @RequestParam("ip") String ip) {
        if (file.isEmpty()) {
            throw new CustomException("请选择一个文件上传");
        }
        if (StringUtils.isBlank(currentPath)) {
            currentPath = "/";
        }
        if (!currentPath.endsWith("/")) {
            currentPath += "/";
        }

        try {
            // 上传目标服务器
            Host remoteHost = hostService.getEnalbeList(ip).get(0);
            Session session = SSHUtil.openSession(remoteHost.getHostIp(), 22, remoteHost.getAccount(),
                    remoteHost.getPassword());
            SSHUtil.uploadFile(session, currentPath + file.getOriginalFilename(), file.getInputStream());
            return R.data("File uploaded successfully");
        } catch (IOException e) {
            e.printStackTrace();
            return R.fail("File upload failed!", "fail");
        }
    }

    /**
     * 下载文件
     */
    @GetMapping("/download")
    public void handleFileDownload(@RequestParam("ip") String ip, @RequestParam("currentPath") String currentPath, @RequestParam("fileName") String fileName, HttpServletResponse response) throws UnsupportedEncodingException {
        if (StringUtils.isBlank(currentPath)) {
            currentPath = "/";
        }
        if (!currentPath.endsWith("/")) {
            currentPath += "/";
        }
        response.setContentType("application/octet-stream");
        FileUtils.setAttachmentResponseHeader(response, fileName);

        try (OutputStream outputStream = response.getOutputStream()) {
            // 目标服务器
            Host remoteHost = hostService.getEnalbeList(ip).get(0);
            Session session = SSHUtil.openSession(remoteHost.getHostIp(), 22, remoteHost.getAccount(),
                    remoteHost.getPassword());
            SSHUtil.downloadFile(session, currentPath + fileName, outputStream);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 查询文件中心列表
     */
    @PreAuthorize("@ss.hasPermi('dockerinsight:fileSystem:list')")
    @GetMapping("/list")
    public R<PageInfo> list(FileSystem fileSystem, HttpServletRequest request, HttpServletResponse response) {
        fileSystem.setPage(new PageDomain(request, response));
        return R.data(fileSystemService.findPage(fileSystem));
    }

    /**
     * 获取文件中心详细信息
     */
    @PreAuthorize("@ss.hasPermi('dockerinsight:fileSystem:query')")
    @GetMapping(value = "/{id}")
    public R<FileSystem> detail(@PathVariable("id") String id) {
        return R.data(fileSystemService.get(id));
    }

    /**
     * 新增文件中心
     */
    @PreAuthorize("@ss.hasPermi('dockerinsight:fileSystem:add')")
    @Log(title = "文件中心", businessType = BusinessType.INSERT)
    @PostMapping
    public R add(@RequestBody @Validated FileSystem fileSystem) {
        return R.status(fileSystemService.save(fileSystem));
    }

    /**
     * 修改文件中心
     */
    @PreAuthorize("@ss.hasPermi('dockerinsight:fileSystem:edit')")
    @Log(title = "文件中心", businessType = BusinessType.UPDATE)
    @PutMapping
    public R edit(@RequestBody @Validated FileSystem fileSystem) {
        return R.status(fileSystemService.save(fileSystem));
    }

    /**
     * 删除文件中心
     */
    @PreAuthorize("@ss.hasPermi('dockerinsight:fileSystem:remove')")
    @Log(title = "文件中心", businessType = BusinessType.DELETE)
    @DeleteMapping("/{ids}")
    public R remove(@PathVariable String[] ids) {
        return R.status(fileSystemService.deleteFileSystemByIds(ids));
    }


    /**
     * 导出文件中心列表
     */
    @PreAuthorize("@ss.hasPermi('dockerinsight:fileSystem:export')")
    @Log(title = "文件中心", businessType = BusinessType.EXPORT)
    @GetMapping("/export")
    public R export(FileSystem fileSystem) {
        List<FileSystem> list = fileSystemService.findList(fileSystem);
        ExcelUtil<FileSystem> util = new ExcelUtil<FileSystem>(FileSystem.class);
        return util.exportExcel(list, "文件中心数据");
    }

    /**
     * 根据字典类型查询字典数据信息等其他自定义信息
     */
    @GetMapping(value = "/getInitData/{dictTypes}")
    public R getInitData(@PathVariable String dictTypes) {
        Map<String, Object> dataMap = new HashMap<String, Object>();
        dataMap.putAll(DictUtils.getMultiDictList(dictTypes));
        return R.data(dataMap);
    }

}
